﻿using System;
using System.Net;
using System.ComponentModel;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using System.IO;

namespace FrameworkQ.WP7.Utility
{
    public class CachedInetAccess
    {
        public class ContentAvailableEventArgs : AsyncCompletedEventArgs
        {
            public string Result { get; internal set; }
            public Exception Error { get; internal set; }
            public object UserState { get; internal set; }
        }

        public delegate void OnContentAvailable(object sender, ContentAvailableEventArgs args);

        internal class UserState
        {
            public string StorePath { get; internal set; }
            public object UserObject { get; internal set; }
            public WebClient Client { get; internal set; }            
            public OnContentAvailable Handler { get; internal set; }
        }

        private List<WebClient> _activeClients = new List<WebClient>();

        public static string GetLocalPath(string address)
        {
            string hash = GetUrlHash(address);
            string path = @".\cache\" + hash;
            return path;
        }

        public void GetWebContent(string address, object userObject, OnContentAvailable onContentAvailableHandler)
        {
            string hash = GetUrlHash(address);
            string path = @".\cache\" + hash;
            string content = string.Empty;
            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                
                if (iso.FileExists(path))
                {
                    // We already have it
                    using (IsolatedStorageFileStream ifs = iso.OpenFile(path, FileMode.Open, FileAccess.Read))
                    {
                        using (StreamReader reader = new StreamReader(ifs))
                        {
                            content = reader.ReadToEnd();
                        }
                    }
                    ContentAvailableEventArgs args = new ContentAvailableEventArgs()
                    {
                        Result = content, UserState = userObject
                    };
                    if (onContentAvailableHandler != null)
                    {
                        onContentAvailableHandler(this, args);
                    }
                }
                else
                {
                    Uri url = new Uri(address, UriKind.Absolute);
                    WebClient client = new WebClient();
                    client.DownloadStringCompleted += new DownloadStringCompletedEventHandler(client_DownloadStringCompleted);
                    UserState state = new UserState() { UserObject = userObject, Client = client, Handler = onContentAvailableHandler, StorePath = path};
                    client.DownloadStringAsync(url, state);
                    _activeClients.Add(client);
                }
            }
        }

        void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            UserState state = e.UserState as UserState;
            _activeClients.Remove(state.Client);


            using (IsolatedStorageFile iso = IsolatedStorageFile.GetUserStoreForApplication())
            {
                if (! iso.DirectoryExists( @".\cache"))
                {
                    iso.CreateDirectory(@"cache");
                }
                using (IsolatedStorageFileStream strm = iso.CreateFile(state.StorePath))
                {
                    using (StreamWriter writer = new StreamWriter(strm))
                    {
                        writer.Write(e.Result);
                    }
                }
            }

            ContentAvailableEventArgs args = new ContentAvailableEventArgs()
            {
                Result = e.Result, Error = e.Error, UserState = state.UserObject
            };
            if (state.Handler != null)
            {
                state.Handler(sender, args);
            }
        }

        private static string GetUrlHash(string url)
        {
            return url.Replace(':', '-').Replace('/', '-').Replace('\\', '-').Replace('&', '-').Replace('%', '-');
        }
    }
}